package com.rtline.business.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.service.IService;
import com.rtline.business.enums.ServiceType;
import com.rtline.business.handler.CustomHorizontalCellStyleStrategy;
import com.rtline.business.handler.CustomSheetWriteHandler;
import com.rtline.business.listener.ExcelDataListener;
import com.rtline.business.utils.ValidateGlobalCacheUtils;
import com.rtline.business.vo.ImportResult;
import com.rtline.business.vo.OrderVo;
import com.rtline.business.vo.UserVo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;


@RestController
@RequestMapping("/file/new")
@Slf4j
public class FileControllerNew {

    @Autowired
    private ApplicationContext applicationContext;


    @Autowired
    private ThreadPoolExecutor taskExecutor;

    private static void importDeal(HttpServletResponse response, List<UserVo> userVoList, List<OrderVo> orderVoList) {
        // 定义Sheet信息
        Map<Integer, String[]> dropdownOptionsOrder = new HashMap<>();
        dropdownOptionsOrder.put(2, new String[]{"已下单", "已支付"}); // 第3列（索引为2）有下拉框

        WriteSheet userSheet = EasyExcel.writerSheet("user").head(UserVo.class)
                .registerWriteHandler(new CustomHorizontalCellStyleStrategy())
                .build();

        WriteSheet orderSheet = EasyExcel.writerSheet("order").head(OrderVo.class)
                .registerWriteHandler(new CustomHorizontalCellStyleStrategy())
                .registerWriteHandler(new CustomSheetWriteHandler(dropdownOptionsOrder)).build();

        // 写入数据到 Excel
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) {
            excelWriter.write(userVoList, userSheet);
            excelWriter.write(orderVoList, orderSheet);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 下载模板
     *
     * @param response
     * @throws IOException
     * @throws ExecutionException
     * @throws InterruptedException
     * @author Tao Ren
     * @date 2025/6/4 10:11
     * @since 1.0.0
     */
    @GetMapping("/import/template")
    public void exportMultiSheetTemplateParallel(HttpServletResponse response) throws IOException, ExecutionException, InterruptedException {
        // 设置响应头信息
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        // 拼接文件名
        String fileName = "template" + ".xlsx";
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);

        // 创建两个 Sheet 的数据
        List<UserVo> userVoList = new ArrayList<>();
        userVoList.add(new UserVo());
        userVoList.add(new UserVo());

        List<OrderVo> orderVoList = new ArrayList<>();
        orderVoList.add(new OrderVo());
        orderVoList.add(new OrderVo());

        // 创建 WriteSheet 对象
        importDeal(response, userVoList, orderVoList);
    }

    /**
     * 数据导入，返回校验的结果
     *
     * @param file
     * @return
     * @throws IOException
     * @author Tao Ren
     * @date 2025/6/4 10:12
     * @since 1.0.0
     */
    @PostMapping("/import")
    public List<ImportResult> importExcel(@RequestParam("file") MultipartFile file) throws IOException {


        // 生成导入唯一id
        String importIdent = initImportIdent();

        // 获取Sheet页数量
        List<ReadSheet> readSheets = EasyExcel.read(file.getInputStream()).build()
                .excelExecutor()
                .sheetList();
        System.out.println("Sheet页数量: " + readSheets.size());

        // 创建任务列表
        List<CompletableFuture<ImportResult>> futures = new ArrayList<>();
        for (int i = 0; i < readSheets.size(); i++) {
            //获取sheet名称
            String type = readSheets.get(i).getSheetName();
            ServiceType serviceType = ServiceType.getByKey(type);
            String beanName = serviceType.getBeanName();

            int num = i;
            futures.add(CompletableFuture.supplyAsync(() -> {
                ExcelDataListener listener = new ExcelDataListener((IService) applicationContext.getBean(beanName));
                try {
                    EasyExcel.read(file.getInputStream(), serviceType.getClazz(), listener)
                            .sheet(num)
                            .doRead();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

                // 将数据放入缓存
                ValidateGlobalCacheUtils.putExcelData(StrUtil.format("{}-{}", importIdent, type), listener.getAllList());

                List<Object> list = ValidateGlobalCacheUtils.getExcelData(StrUtil.format("{}-{}", importIdent, type));
                log.info(StrUtil.format("ValidateGlobalCacheUtils.getExcelData-{}", list.toString()));

                int failCount = listener.getFailCount();
                int successCount = listener.getSuccessCount();
                int totalCount = listener.getTotalCount();
                return new ImportResult(type, totalCount, successCount, failCount, importIdent);
            }));
        }

        // 等待所有任务完成并收集结果
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0]));

        // 获取所有任务的结果
        CompletableFuture<List<ImportResult>> allResultsFuture = allFutures.thenApply(v -> {
            List<ImportResult> results = new ArrayList<>();
            for (CompletableFuture<ImportResult> future : futures) {
                try {
                    results.add(future.get());
                } catch (InterruptedException | ExecutionException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
            }
            return results;
        });

        List<ImportResult> results = null;
        try {
            results = allResultsFuture.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        return results;
    }

    private String initImportIdent() {
        return UUID.randomUUID().toString(true);
    }

    @GetMapping("/export/result")
    public void exportResult(HttpServletResponse response, @RequestParam String importIdent) throws IOException, ExecutionException, InterruptedException {
        // 设置响应头信息
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        // 拼接文件名
        String fileName = "template" + ".xlsx";
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);

        // 创建两个 Sheet 的数据
        List<UserVo> userVoList = ValidateGlobalCacheUtils.getExcelData(StrUtil.format("{}-{}", importIdent, "user"));


        List<OrderVo> orderVoList = ValidateGlobalCacheUtils.getExcelData(StrUtil.format("{}-{}", importIdent, "order"));

        // 假设 response.getOutputStream() 是你的输出流
        OutputStream outputStream = response.getOutputStream();

        // 创建 ExcelWriter
        ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

        // 创建异步任务列表
        List<CompletableFuture> completableFutures = new ArrayList<>();

        // 异步写入用户数据
        CompletableFuture<Void> userFuture = CompletableFuture.runAsync(() -> {
            WriteSheet userSheet = EasyExcel.writerSheet("user").head(UserVo.class).build();
            synchronized (excelWriter) {
                excelWriter.write(userVoList, userSheet);
            }
        }, taskExecutor);
        completableFutures.add(userFuture);

        // 异步写入订单数据
        CompletableFuture<Void> orderFuture = CompletableFuture.runAsync(() -> {
            WriteSheet orderSheet = EasyExcel.writerSheet("order").head(OrderVo.class).build();
            synchronized (excelWriter) {
                excelWriter.write(orderVoList, orderSheet);
            }
        }, taskExecutor);
        completableFutures.add(orderFuture);

        // 等待所有异步任务完成
        for (CompletableFuture completableFuture : completableFutures) {
            completableFuture.join();
        }

        // 刷新流并关闭 ExcelWriter
        excelWriter.finish();

        // 关闭线程池
        taskExecutor.shutdown();


        // importDeal(response, userVoList, orderVoList);
        // 清理输出流
        outputStream.flush();
        outputStream.close();
    }

    @GetMapping("/generate-template")
    public ResponseEntity<StreamingResponseBody> generateTemplate(HttpServletResponse response) {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=template.xlsx");

        // 定义Sheet信息

        Map<Integer, String[]> dropdownOptionsOrder = new HashMap<>();
        dropdownOptionsOrder.put(2, new String[]{"已下单", "已支付"}); // 第3列（索引为2）有下拉框

        WriteSheet userSheet = EasyExcel.writerSheet("user").head(UserVo.class)
                .registerWriteHandler(new CustomHorizontalCellStyleStrategy())
                .build();

        WriteSheet orderSheet = EasyExcel.writerSheet("order").head(OrderVo.class)
                .registerWriteHandler(new CustomHorizontalCellStyleStrategy())
                .registerWriteHandler(new CustomSheetWriteHandler(dropdownOptionsOrder)).build();
        // 写入数据到 Excel
        StreamingResponseBody stream = outputStream -> {
            try (ExcelWriter excelWriter = EasyExcel.write(outputStream).build()) {
                excelWriter.write(new ArrayList<>(), userSheet);
                excelWriter.write(new ArrayList<>(), orderSheet);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };

        return ResponseEntity.ok(stream);
    }
}
